﻿module hxy.JsGame {
    export class GameManager {
        private _spriteManager: SpriteManager;
        private _player: ConcreteSprite.PlayerTank;

        constructor(spriteManager: SpriteManager) {
            this._spriteManager = spriteManager;
        }

        Initialize() {
            this._player = this._spriteManager.AddAPlayer();
            for (var i = 0; i < 5; i++) {
                this._spriteManager.AddAEnemy().Fire();
            }
            setInterval(() => this.ThreadRun(), 20);
            setInterval(() => this.UpdateExplosionFrame(), 150);

            document.addEventListener("keydown", e => this.KeyDown(e));
            document.addEventListener("keyup", e => this.KeyUp(e));
        }
        ThreadRun() {
            for (var i = 0; i < this._spriteManager.allSprites.length; i++) {
                var sprite = this._spriteManager.allSprites[i];
                sprite.Move();

                this.DealCollideSprites(sprite);
            
                //change enemy direction by a random time span
                if (Math.random() * 100 < 1 &&
                    sprite.collisionType == Enum.CollisionType.EnemyTank) {
                    sprite.ChangeARandomDirection();
                }
            }
        }
        UpdateExplosionFrame() {
            this._spriteManager.explosions.forEach(function (explosion: ConcreteSprite.Explosion) {
                if (explosion.isVisible) {
                    explosion.UpdateFrame();
                }
            });
        }
        DealCollideSprites(sprite: Common.SpriteBase) {
            //Don't detect a collision generated by a explosion
            if (sprite.collisionType == Enum.CollisionType.Explosion) {
                return;
            }
            var allSprites = this._spriteManager.allSprites;

            for (var j = 0; j < allSprites.length; j++) {
                var target = allSprites[j];
                //Is Need To Detect Collision between sprite and target
                if (this.IsNeedToDetectCollision(sprite, target)) {
                    if (sprite.IsCollided(target)) {
                        sprite.OnCollided(target.rectangle, target.collisionType, true);
                        target.OnCollided(sprite.rectangle, sprite.collisionType, false);
                        //need return!
                        //otherwise occurs the same type collision
                        return;
                    }
                }
            }
        }
        IsNeedToDetectCollision(sprite1: Common.SpriteBase, sprite2: Common.SpriteBase) {
            if (sprite1 == sprite2) {
                return false;
            }
            if (sprite1.collisionType == Enum.CollisionType.Explosion ||
                sprite2.collisionType == Enum.CollisionType.Explosion) {
                return false;
            }
            if (sprite1 instanceof ConcreteSprite.Shell && sprite1.myTank == sprite2) {
                return false;
            }
            if (sprite2 instanceof ConcreteSprite.Shell && sprite2.myTank == sprite1) {
                return false;
            }
            return true;
        }
        KeyDown(e: KeyboardEvent) {
            switch (e.keyCode) {
                case KeyCodes.left:
                    this._player.direction = Enum.Direction.Left;
                    this._player.isActive = true;
                    break;
                case KeyCodes.up:
                    this._player.direction = Enum.Direction.Up;
                    this._player.isActive = true;
                    break;
                case KeyCodes.right:
                    this._player.direction = Enum.Direction.Right;
                    this._player.isActive = true;
                    break;
                case KeyCodes.down:
                    this._player.direction = Enum.Direction.Down;
                    this._player.isActive = true;
                    break;
            }
        }
        KeyUp(e) {
            this._player.isActive = false;
            switch (e.keyCode) {
                case KeyCodes.space:
                    this._player.Fire();
                    break;
            }
        }
    }
}